/*******************************************************************************
 * Copyright (c) 2014, Jean-David Gadina - www.xs-labs.com / www.digidna.net
 * Distributed under the Boost Software License, Version 1.0.
 * 
 * Boost Software License - Version 1.0 - August 17th, 2003
 * 
 * Permission is hereby granted, free of charge, to any person or organization
 * obtaining a copy of the software and accompanying documentation covered by
 * this license (the "Software") to use, reproduce, display, distribute,
 * execute, and transmit the Software, and to prepare derivative works of the
 * Software, and to permit third-parties to whom the Software is furnished to
 * do so, all subject to the following:
 * 
 * The copyright notices in the Software and this entire statement, including
 * the above license grant, this restriction and the following disclaimer,
 * must be included in all copies of the Software, in whole or in part, and
 * all derivative works of the Software, unless such copies or derivative
 * works are solely in the form of machine-executable object code generated by
 * a source language processor.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
 * SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
 * FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
 * DEALINGS IN THE SOFTWARE.
 ******************************************************************************/

/*!
 * @header      CFPP-Number.h
 * @copyright   (c) 2014 - Jean-David Gadina - www.xs-labs.com / www.digidna.net
 * @abstract    CoreFoundation++ CFNumberRef wrapper
 */

#ifndef CFPP_NUMBER_H
#define CFPP_NUMBER_H

#include <stdint.h>

#ifdef __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wc++11-long-long" /* Do not warn about long long in C++98 */
#endif

namespace CF
{
    class CFPP_EXPORT Number: public PropertyListType< Number >
    {
        public:

            Number( void );
            Number( const AutoPointer & value );
            Number( CFTypeRef cfObject );
            Number( CFNumberRef cfObject );
            Number( std::nullptr_t );
            Number( const AutoPointer & value, signed char defaultValueIfNULL );
            Number( const AutoPointer & value, signed short defaultValueIfNULL );
            Number( const AutoPointer & value, signed int defaultValueIfNULL );
            Number( const AutoPointer & value, signed long defaultValueIfNULL );
            Number( const AutoPointer & value, signed long long defaultValueIfNULL );
            Number( const AutoPointer & value, unsigned char defaultValueIfNULL );
            Number( const AutoPointer & value, unsigned short defaultValueIfNULL );
            Number( const AutoPointer & value, unsigned int defaultValueIfNULL );
            Number( const AutoPointer & value, unsigned long defaultValueIfNULL );
            Number( const AutoPointer & value, unsigned long long defaultValueIfNULL );
            Number( const AutoPointer & value, float defaultValueIfNULL );
            Number( const AutoPointer & value, double defaultValueIfNULL );
            Number( CFTypeRef cfObject, signed char defaultValueIfNULL );
            Number( CFTypeRef cfObject, signed short defaultValueIfNULL );
            Number( CFTypeRef cfObject, signed int defaultValueIfNULL );
            Number( CFTypeRef cfObject, signed long defaultValueIfNULL );
            Number( CFTypeRef cfObject, signed long long defaultValueIfNULL );
            Number( CFTypeRef cfObject, unsigned char defaultValueIfNULL );
            Number( CFTypeRef cfObject, unsigned short defaultValueIfNULL );
            Number( CFTypeRef cfObject, unsigned int defaultValueIfNULL );
            Number( CFTypeRef cfObject, unsigned long defaultValueIfNULL );
            Number( CFTypeRef cfObject, unsigned long long defaultValueIfNULL );
            Number( CFTypeRef cfObject, float defaultValueIfNULL );
            Number( CFTypeRef cfObject, double defaultValueIfNULL );
            Number( CFNumberRef cfObject, signed char defaultValueIfNULL );
            Number( CFNumberRef cfObject, signed short defaultValueIfNULL );
            Number( CFNumberRef cfObject, signed int defaultValueIfNULL );
            Number( CFNumberRef cfObject, signed long defaultValueIfNULL );
            Number( CFNumberRef cfObject, signed long long defaultValueIfNULL );
            Number( CFNumberRef cfObject, unsigned char defaultValueIfNULL );
            Number( CFNumberRef cfObject, unsigned short defaultValueIfNULL );
            Number( CFNumberRef cfObject, unsigned int defaultValueIfNULL );
            Number( CFNumberRef cfObject, unsigned long defaultValueIfNULL );
            Number( CFNumberRef cfObject, unsigned long long defaultValueIfNULL );
            Number( CFNumberRef cfObject, float defaultValueIfNULL );
            Number( CFNumberRef cfObject, double defaultValueIfNULL );
            Number( const Number & value );
            Number( signed char value );
            Number( signed short value );
            Number( signed int value );
            Number( signed long value );
            Number( signed long long value );
            Number( unsigned char value );
            Number( unsigned short value );
            Number( unsigned int value );
            Number( unsigned long value );
            Number( unsigned long long value );
            Number( float value );
            Number( double value );
            Number( Number && value ) noexcept;
            
            virtual ~Number( void );
            
            Number & operator = ( Number value );
            Number & operator = ( const AutoPointer & value );
            Number & operator = ( CFTypeRef value );
            Number & operator = ( CFNumberRef value );
            Number & operator = ( std::nullptr_t value );
            Number & operator = ( signed char value );
            Number & operator = ( signed short value );
            Number & operator = ( signed int value );
            Number & operator = ( signed long value );
            Number & operator = ( signed long long value );
            Number & operator = ( unsigned char value );
            Number & operator = ( unsigned short value );
            Number & operator = ( unsigned int value );
            Number & operator = ( unsigned long value );
            Number & operator = ( unsigned long long value );
            Number & operator = ( float value );
            Number & operator = ( double value );
            
            bool operator == ( const Number & value ) const;
            bool operator == ( CFTypeRef value ) const;
            bool operator == ( CFNumberRef value ) const;
            bool operator == ( signed char value ) const;
            bool operator == ( signed short value ) const;
            bool operator == ( signed int value ) const;
            bool operator == ( signed long value ) const;
            bool operator == ( signed long long value ) const;
            bool operator == ( unsigned char value ) const;
            bool operator == ( unsigned short value ) const;
            bool operator == ( unsigned int value ) const;
            bool operator == ( unsigned long value ) const;
            bool operator == ( unsigned long long value ) const;
            bool operator == ( float value ) const;
            bool operator == ( double value ) const;
            
            bool operator != ( const Number & value ) const;
            bool operator != ( CFTypeRef value ) const;
            bool operator != ( CFNumberRef value ) const;
            bool operator != ( signed char value ) const;
            bool operator != ( signed short value ) const;
            bool operator != ( signed int value ) const;
            bool operator != ( signed long value ) const;
            bool operator != ( signed long long value ) const;
            bool operator != ( unsigned char value ) const;
            bool operator != ( unsigned short value ) const;
            bool operator != ( unsigned int value ) const;
            bool operator != ( unsigned long value ) const;
            bool operator != ( unsigned long long value ) const;
            bool operator != ( float value ) const;
            bool operator != ( double value ) const;
            
            bool operator >= ( const Number & value ) const;
            bool operator >= ( CFTypeRef value ) const;
            bool operator >= ( CFNumberRef value ) const;
            bool operator >= ( signed char value ) const;
            bool operator >= ( signed short value ) const;
            bool operator >= ( signed int value ) const;
            bool operator >= ( signed long value ) const;
            bool operator >= ( signed long long value ) const;
            bool operator >= ( unsigned char value ) const;
            bool operator >= ( unsigned short value ) const;
            bool operator >= ( unsigned int value ) const;
            bool operator >= ( unsigned long value ) const;
            bool operator >= ( unsigned long long value ) const;
            bool operator >= ( float value ) const;
            bool operator >= ( double value ) const;
            
            bool operator <= ( const Number & value ) const;
            bool operator <= ( CFTypeRef value ) const;
            bool operator <= ( CFNumberRef value ) const;
            bool operator <= ( signed char value ) const;
            bool operator <= ( signed short value ) const;
            bool operator <= ( signed int value ) const;
            bool operator <= ( signed long value ) const;
            bool operator <= ( signed long long value ) const;
            bool operator <= ( unsigned char value ) const;
            bool operator <= ( unsigned short value ) const;
            bool operator <= ( unsigned int value ) const;
            bool operator <= ( unsigned long value ) const;
            bool operator <= ( unsigned long long value ) const;
            bool operator <= ( float value ) const;
            bool operator <= ( double value ) const;
            
            bool operator > ( const Number & value ) const;
            bool operator > ( CFTypeRef value ) const;
            bool operator > ( CFNumberRef value ) const;
            bool operator > ( signed char value ) const;
            bool operator > ( signed short value ) const;
            bool operator > ( signed int value ) const;
            bool operator > ( signed long value ) const;
            bool operator > ( signed long long value ) const;
            bool operator > ( unsigned char value ) const;
            bool operator > ( unsigned short value ) const;
            bool operator > ( unsigned int value ) const;
            bool operator > ( unsigned long value ) const;
            bool operator > ( unsigned long long value ) const;
            bool operator > ( float value ) const;
            bool operator > ( double value ) const;
            
            bool operator < ( const Number & value ) const;
            bool operator < ( CFTypeRef value ) const;
            bool operator < ( CFNumberRef value ) const;
            bool operator < ( signed char value ) const;
            bool operator < ( signed short value ) const;
            bool operator < ( signed int value ) const;
            bool operator < ( signed long value ) const;
            bool operator < ( signed long long value ) const;
            bool operator < ( unsigned char value ) const;
            bool operator < ( unsigned short value ) const;
            bool operator < ( unsigned int value ) const;
            bool operator < ( unsigned long value ) const;
            bool operator < ( unsigned long long value ) const;
            bool operator < ( float value ) const;
            bool operator < ( double value ) const;
            
            bool operator && ( const Number & value ) const;
            bool operator && ( CFTypeRef value ) const;
            bool operator && ( CFNumberRef value ) const;
            bool operator && ( signed char value ) const;
            bool operator && ( signed short value ) const;
            bool operator && ( signed int value ) const;
            bool operator && ( signed long value ) const;
            bool operator && ( signed long long value ) const;
            bool operator && ( unsigned char value ) const;
            bool operator && ( unsigned short value ) const;
            bool operator && ( unsigned int value ) const;
            bool operator && ( unsigned long value ) const;
            bool operator && ( unsigned long long value ) const;
            bool operator && ( float value ) const;
            bool operator && ( double value ) const;
            
            bool operator || ( const Number & value ) const;
            bool operator || ( CFTypeRef value ) const;
            bool operator || ( CFNumberRef value ) const;
            bool operator || ( signed char value ) const;
            bool operator || ( signed short value ) const;
            bool operator || ( signed int value ) const;
            bool operator || ( signed long value ) const;
            bool operator || ( signed long long value ) const;
            bool operator || ( unsigned char value ) const;
            bool operator || ( unsigned short value ) const;
            bool operator || ( unsigned int value ) const;
            bool operator || ( unsigned long value ) const;
            bool operator || ( unsigned long long value ) const;
            bool operator || ( float value ) const;
            bool operator || ( double value ) const;
            
            Number & operator ~ ( void );
            Number & operator ! ( void );
            Number & operator ++ ( void );
            Number   operator ++ ( int );
            Number & operator -- ( void );
            Number   operator -- ( int );
            
            Number & operator += ( const Number & value );
            Number & operator += ( CFNumberRef value );
            Number & operator += ( signed char value );
            Number & operator += ( signed short value );
            Number & operator += ( signed int value );
            Number & operator += ( signed long value );
            Number & operator += ( signed long long value );
            Number & operator += ( unsigned char value );
            Number & operator += ( unsigned short value );
            Number & operator += ( unsigned int value );
            Number & operator += ( unsigned long value );
            Number & operator += ( unsigned long long value );
            Number & operator += ( float value );
            Number & operator += ( double value );
            
            Number & operator -= ( const Number & value );
            Number & operator -= ( CFNumberRef value );
            Number & operator -= ( signed char value );
            Number & operator -= ( signed short value );
            Number & operator -= ( signed int value );
            Number & operator -= ( signed long value );
            Number & operator -= ( signed long long value );
            Number & operator -= ( unsigned char value );
            Number & operator -= ( unsigned short value );
            Number & operator -= ( unsigned int value );
            Number & operator -= ( unsigned long value );
            Number & operator -= ( unsigned long long value );
            Number & operator -= ( float value );
            Number & operator -= ( double value );
            
            Number & operator *= ( const Number & value );
            Number & operator *= ( CFNumberRef value );
            Number & operator *= ( signed char value );
            Number & operator *= ( signed short value );
            Number & operator *= ( signed int value );
            Number & operator *= ( signed long value );
            Number & operator *= ( signed long long value );
            Number & operator *= ( unsigned char value );
            Number & operator *= ( unsigned short value );
            Number & operator *= ( unsigned int value );
            Number & operator *= ( unsigned long value );
            Number & operator *= ( unsigned long long value );
            Number & operator *= ( float value );
            Number & operator *= ( double value );
            
            Number & operator /= ( const Number & value );
            Number & operator /= ( CFNumberRef value );
            Number & operator /= ( signed char value );
            Number & operator /= ( signed short value );
            Number & operator /= ( signed int value );
            Number & operator /= ( signed long value );
            Number & operator /= ( signed long long value );
            Number & operator /= ( unsigned char value );
            Number & operator /= ( unsigned short value );
            Number & operator /= ( unsigned int value );
            Number & operator /= ( unsigned long value );
            Number & operator /= ( unsigned long long value );
            Number & operator /= ( float value );
            Number & operator /= ( double value );
            
            Number & operator |= ( const Number & value );
            Number & operator |= ( CFNumberRef value );
            Number & operator |= ( signed char value );
            Number & operator |= ( signed short value );
            Number & operator |= ( signed int value );
            Number & operator |= ( signed long value );
            Number & operator |= ( signed long long value );
            Number & operator |= ( unsigned char value );
            Number & operator |= ( unsigned short value );
            Number & operator |= ( unsigned int value );
            Number & operator |= ( unsigned long value );
            Number & operator |= ( unsigned long long value );
            
            Number & operator &= ( const Number & value );
            Number & operator &= ( CFNumberRef value );
            Number & operator &= ( signed char value );
            Number & operator &= ( signed short value );
            Number & operator &= ( signed int value );
            Number & operator &= ( signed long value );
            Number & operator &= ( signed long long value );
            Number & operator &= ( unsigned char value );
            Number & operator &= ( unsigned short value );
            Number & operator &= ( unsigned int value );
            Number & operator &= ( unsigned long value );
            Number & operator &= ( unsigned long long value );
            
            Number & operator %= ( const Number & value );
            Number & operator %= ( CFNumberRef value );
            Number & operator %= ( signed char value );
            Number & operator %= ( signed short value );
            Number & operator %= ( signed int value );
            Number & operator %= ( signed long value );
            Number & operator %= ( signed long long value );
            Number & operator %= ( unsigned char value );
            Number & operator %= ( unsigned short value );
            Number & operator %= ( unsigned int value );
            Number & operator %= ( unsigned long value );
            Number & operator %= ( unsigned long long value );
            
            Number & operator ^= ( const Number & value );
            Number & operator ^= ( CFNumberRef value );
            Number & operator ^= ( signed char value );
            Number & operator ^= ( signed short value );
            Number & operator ^= ( signed int value );
            Number & operator ^= ( signed long value );
            Number & operator ^= ( signed long long value );
            Number & operator ^= ( unsigned char value );
            Number & operator ^= ( unsigned short value );
            Number & operator ^= ( unsigned int value );
            Number & operator ^= ( unsigned long value );
            Number & operator ^= ( unsigned long long value );
            
            Number & operator <<= ( const Number & value );
            Number & operator <<= ( CFNumberRef value );
            Number & operator <<= ( signed char value );
            Number & operator <<= ( signed short value );
            Number & operator <<= ( signed int value );
            Number & operator <<= ( signed long value );
            Number & operator <<= ( signed long long value );
            Number & operator <<= ( unsigned char value );
            Number & operator <<= ( unsigned short value );
            Number & operator <<= ( unsigned int value );
            Number & operator <<= ( unsigned long value );
            Number & operator <<= ( unsigned long long value );
            
            Number & operator >>= ( const Number & value );
            Number & operator >>= ( CFNumberRef value );
            Number & operator >>= ( signed char value );
            Number & operator >>= ( signed short value );
            Number & operator >>= ( signed int value );
            Number & operator >>= ( signed long value );
            Number & operator >>= ( signed long long value );
            Number & operator >>= ( unsigned char value );
            Number & operator >>= ( unsigned short value );
            Number & operator >>= ( unsigned int value );
            Number & operator >>= ( unsigned long value );
            Number & operator >>= ( unsigned long long value );
            
            Number operator + ( const Number & value );
            Number operator + ( CFNumberRef value );
            Number operator + ( signed char value );
            Number operator + ( signed short value );
            Number operator + ( signed int value );
            Number operator + ( signed long value );
            Number operator + ( signed long long value );
            Number operator + ( unsigned char value );
            Number operator + ( unsigned short value );
            Number operator + ( unsigned int value );
            Number operator + ( unsigned long value );
            Number operator + ( unsigned long long value );
            Number operator + ( float value );
            Number operator + ( double value );
            
            Number operator - ( const Number & value );
            Number operator - ( CFNumberRef value );
            Number operator - ( signed char value );
            Number operator - ( signed short value );
            Number operator - ( signed int value );
            Number operator - ( signed long value );
            Number operator - ( signed long long value );
            Number operator - ( unsigned char value );
            Number operator - ( unsigned short value );
            Number operator - ( unsigned int value );
            Number operator - ( unsigned long value );
            Number operator - ( unsigned long long value );
            Number operator - ( float value );
            Number operator - ( double value );
            
            Number operator * ( const Number & value );
            Number operator * ( CFNumberRef value );
            Number operator * ( signed char value );
            Number operator * ( signed short value );
            Number operator * ( signed int value );
            Number operator * ( signed long value );
            Number operator * ( signed long long value );
            Number operator * ( unsigned char value );
            Number operator * ( unsigned short value );
            Number operator * ( unsigned int value );
            Number operator * ( unsigned long value );
            Number operator * ( unsigned long long value );
            Number operator * ( float value );
            Number operator * ( double value );
            
            Number operator / ( const Number & value );
            Number operator / ( CFNumberRef value );
            Number operator / ( signed char value );
            Number operator / ( signed short value );
            Number operator / ( signed int value );
            Number operator / ( signed long value );
            Number operator / ( signed long long value );
            Number operator / ( unsigned char value );
            Number operator / ( unsigned short value );
            Number operator / ( unsigned int value );
            Number operator / ( unsigned long value );
            Number operator / ( unsigned long long value );
            Number operator / ( float value );
            Number operator / ( double value );
            
            Number operator % ( const Number & value );
            Number operator % ( CFNumberRef value );
            Number operator % ( signed char value );
            Number operator % ( signed short value );
            Number operator % ( signed int value );
            Number operator % ( signed long value );
            Number operator % ( signed long long value );
            Number operator % ( unsigned char value );
            Number operator % ( unsigned short value );
            Number operator % ( unsigned int value );
            Number operator % ( unsigned long value );
            Number operator % ( unsigned long long value );
        
            Number operator & ( const Number & value );
            Number operator & ( CFNumberRef value );
            Number operator & ( signed char value );
            Number operator & ( signed short value );
            Number operator & ( signed int value );
            Number operator & ( signed long value );
            Number operator & ( signed long long value );
            Number operator & ( unsigned char value );
            Number operator & ( unsigned short value );
            Number operator & ( unsigned int value );
            Number operator & ( unsigned long value );
            Number operator & ( unsigned long long value );
        
            
            Number operator | ( const Number & value );
            Number operator | ( CFNumberRef value );
            Number operator | ( signed char value );
            Number operator | ( signed short value );
            Number operator | ( signed int value );
            Number operator | ( signed long value );
            Number operator | ( signed long long value );
            Number operator | ( unsigned char value );
            Number operator | ( unsigned short value );
            Number operator | ( unsigned int value );
            Number operator | ( unsigned long value );
            Number operator | ( unsigned long long value );
            
            Number operator ^ ( const Number & value );
            Number operator ^ ( CFNumberRef value );
            Number operator ^ ( signed char value );
            Number operator ^ ( signed short value );
            Number operator ^ ( signed int value );
            Number operator ^ ( signed long value );
            Number operator ^ ( signed long long value );
            Number operator ^ ( unsigned char value );
            Number operator ^ ( unsigned short value );
            Number operator ^ ( unsigned int value );
            Number operator ^ ( unsigned long value );
            Number operator ^ ( unsigned long long value );
        
            Number operator << ( const Number & value );
            Number operator << ( CFNumberRef value );
            Number operator << ( signed char value );
            Number operator << ( signed short value );
            Number operator << ( signed int value );
            Number operator << ( signed long value );
            Number operator << ( signed long long value );
            Number operator << ( unsigned char value );
            Number operator << ( unsigned short value );
            Number operator << ( unsigned int value );
            Number operator << ( unsigned long value );
            Number operator << ( unsigned long long value );
            
            Number operator >> ( const Number & value );
            Number operator >> ( CFNumberRef value );
            Number operator >> ( signed char value );
            Number operator >> ( signed short value );
            Number operator >> ( signed int value );
            Number operator >> ( signed long value );
			Number operator >> ( signed long long value );
            Number operator >> ( unsigned char value );
            Number operator >> ( unsigned short value );
            Number operator >> ( unsigned int value );
            Number operator >> ( unsigned long value );
			Number operator >> ( unsigned long long value );
            
            operator signed char        () const;
            operator signed short       () const;
            operator signed int         () const;
            operator signed long        () const;
			operator signed long long   () const;
            operator unsigned char      () const;
            operator unsigned short     () const;
            operator unsigned int       () const;
            operator unsigned long      () const;
            operator unsigned long long () const;
            operator float              () const;
            operator double             () const;
            
            virtual CFTypeID  GetTypeID( void ) const;
            virtual CFTypeRef GetCFObject( void ) const;
            
            bool IsFloatType( void ) const;
            
            signed char         GetSignedCharValue( void ) const;
            signed short        GetSignedShortValue( void ) const;
            signed int          GetSignedIntValue( void ) const;
            signed long         GetSignedLongValue( void ) const;
            signed long long    GetSignedLongLongValue( void ) const;
            unsigned char       GetUnsignedCharValue( void ) const;
            unsigned short      GetUnsignedShortValue( void ) const;
            unsigned int        GetUnsignedIntValue( void ) const;
            unsigned long       GetUnsignedLongValue( void ) const;
            unsigned long long  GetUnsignedLongLongValue( void ) const;
            float               GetFloatValue( void ) const;
            double              GetDoubleValue( void ) const;
            
            void SetSignedCharValue( signed char value );
            void SetSignedShortValue( signed short value );
            void SetSignedIntValue( signed int value );
            void SetSignedLongValue( signed long value );
            void SetSignedLongLongValue( signed long long value );
            void SetUnsignedCharValue( unsigned char value );
            void SetUnsignedShortValue( unsigned short value );
            void SetUnsignedIntValue( unsigned int value );
            void SetUnsignedLongValue( unsigned long value );
            void SetUnsignedLongLongValue( unsigned long long value );
            void SetFloatValue( float value );
            void SetDoubleValue( double value );
            
            friend void swap( Number & v1, Number & v2 ) noexcept;
            
        private:
            
            CFNumberRef _cfObject;
    };
}

#ifdef __clang__
#pragma clang diagnostic pop
#endif

#endif /* CFPP_NUMBER_H */
